﻿#include "DataObject.h"
#include "Logging.h"
#include "libmesh/boundary_info.h"
#include "libmesh/elem.h"
#include "libmesh/mesh.h"
#include "libmesh/namebased_io.h"
#include <vtkm/cont/DataSetBuilderExplicit.h>
#include <vtkm/io/VTKDataSetWriter.h>

int main(int argc, char** argv)
{
  libMesh::LibMeshInit init(argc, argv);
  libMesh::Parallel::Communicator comm;

  libMesh::Mesh mesh(comm);

  try
  {
    libMesh::NameBasedIO(mesh).read("cylinder.msh");
  }
  catch (const std::exception& e)
  {
    std::cout << e.what() << std::endl;
  }

  mesh.prepare_for_use();

  std::cout << mesh.n_elem() << std::endl;
  std::cout << mesh.n_nodes() << std::endl;
  mesh.print_info();

  auto& bnd_info = mesh.get_boundary_info();
  std::cout << bnd_info.n_boundary_ids() << std::endl;

  using CoordType = vtkm::Vec3f;
  std::vector<CoordType> coords;
  for (const auto& node : mesh.local_node_ptr_range())
  {
    std::cout << *node << std::endl;
    coords.emplace_back((*node)(0), (*node)(1), (*node)(2));
  }

  std::map<libMesh::ElemType, vtkm::CellShapeIdEnum> libmesh2vtkm{
    { libMesh::ElemType::EDGE2, vtkm::CellShapeIdEnum::CELL_SHAPE_LINE },
    { libMesh::ElemType::TRI3, vtkm::CellShapeIdEnum::CELL_SHAPE_TRIANGLE },
    { libMesh::ElemType::QUAD4, vtkm::CellShapeIdEnum::CELL_SHAPE_QUAD },
    { libMesh::ElemType::TET4, vtkm::CellShapeIdEnum::CELL_SHAPE_TETRA },
    { libMesh::ElemType::HEX8, vtkm::CellShapeIdEnum::CELL_SHAPE_HEXAHEDRON },
    { libMesh::ElemType::PRISM6, vtkm::CellShapeIdEnum::CELL_SHAPE_WEDGE },
    { libMesh::ElemType::PYRAMID5, vtkm::CellShapeIdEnum::CELL_SHAPE_PYRAMID },
  };

  std::vector<vtkm::UInt8> shapes;
  std::vector<IdComponent> numindices;
  std::vector<Id> conn;
  for (const auto& elem : mesh.active_local_element_ptr_range())
  {
    try
    {
      shapes.push_back(libmesh2vtkm.at(elem->type()));
    }
    catch (const std::exception& e)
    {
      console::Error("不支持的单元类型", elem->type());
    }

    numindices.push_back(elem->n_nodes());
    for (size_t i = 0; i < elem->n_nodes(); i++)
    {
      conn.push_back(elem->node_id(i));
    }
  }

  vtkm::cont::DataSetBuilderExplicit dsb;
  auto data_set = dsb.Create(coords, shapes, numindices, conn, "coordinates");

  vtkm::io::VTKDataSetWriter writer("out.vtk");
  writer.WriteDataSet(data_set);

}